package com.mrd.config;

import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.wall.WallConfig;
import com.alibaba.druid.wall.WallFilter;

/**
 * Druid配置
 *
 * @author chenshun
 * @email sunlightcs@gmail.com
 * @date 2017-04-21 0:00
 */
@Configuration
public class DruidConfig {

  private Logger logger = LoggerFactory.getLogger(DruidConfig.class);

  @Value("${spring.datasource.url:#{null}}")
  private String dbUrl;
  @Value("${spring.datasource.username: #{null}}")
  private String username;
  @Value("${spring.datasource.password:#{null}}")
  private String password;
  @Value("${spring.datasource.driverClassName:#{null}}")
  private String driverClassName;
  @Value("${spring.datasource.initialSize:#{null}}")
  private Integer initialSize;
  @Value("${spring.datasource.minIdle:#{null}}")
  private Integer minIdle;
  @Value("${spring.datasource.maxActive:#{null}}")
  private Integer maxActive;
  @Value("${spring.datasource.maxWait:#{null}}")
  private Integer maxWait;
  @Value("${spring.datasource.timeBetweenEvictionRunsMillis:#{null}}")
  private Integer timeBetweenEvictionRunsMillis;
  @Value("${spring.datasource.minEvictableIdleTimeMillis:#{null}}")
  private Integer minEvictableIdleTimeMillis;
  @Value("${spring.datasource.validationQuery:#{null}}")
  private String validationQuery;
  @Value("${spring.datasource.testWhileIdle:#{null}}")
  private Boolean testWhileIdle;
  @Value("${spring.datasource.testOnBorrow:#{null}}")
  private Boolean testOnBorrow;
  @Value("${spring.datasource.testOnReturn:#{null}}")
  private Boolean testOnReturn;
  @Value("${spring.datasource.poolPreparedStatements:#{null}}")
  private Boolean poolPreparedStatements;
  @Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize:#{null}}")
  private Integer maxPoolPreparedStatementPerConnectionSize;
  @Value("${spring.datasource.filters:#{null}}")
  private String filters;
  @Value("{spring.datasource.connectionProperties:#{null}}")
  private String connectionProperties;

  @Bean // 声明其为Bean实例
  @Primary // 在同样的DataSource中，首先使用被标注的DataSource
  public DataSource dataSource() {
    DruidDataSource datasource = new DruidDataSource();

    datasource.setUrl(this.dbUrl);
    datasource.setUsername(username);
    datasource.setPassword(password);
    datasource.setDriverClassName(driverClassName);
    datasource.setDefaultAutoCommit(false);
    // configuration
    if (initialSize != null) {
      datasource.setInitialSize(initialSize);
    }
    if (minIdle != null) {
      datasource.setMinIdle(minIdle);
    }
    if (maxActive != null) {
      datasource.setMaxActive(maxActive);
    }
    if (maxWait != null) {
      datasource.setMaxWait(maxWait);
    }
    if (timeBetweenEvictionRunsMillis != null) {
      datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
    }
    if (minEvictableIdleTimeMillis != null) {
      datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
    }
    if (validationQuery != null) {
      datasource.setValidationQuery(validationQuery);
    }
    if (testWhileIdle != null) {
      datasource.setTestWhileIdle(testWhileIdle);
    }
    if (testOnBorrow != null) {
      datasource.setTestOnBorrow(testOnBorrow);
    }
    if (testOnReturn != null) {
      datasource.setTestOnReturn(testOnReturn);
    }
    if (poolPreparedStatements != null) {
      datasource.setPoolPreparedStatements(poolPreparedStatements);
    }
    if (maxPoolPreparedStatementPerConnectionSize != null) {
      datasource
          .setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
    }

    if (connectionProperties != null) {
      datasource.setConnectionProperties(connectionProperties);
    }

    List<Filter> filters = new ArrayList<>();
    filters.add(statFilter());
    filters.add(wallFilter());
    datasource.setProxyFilters(filters);

    return datasource;
  }

  @Bean
  public ServletRegistrationBean druidServlet() {
    ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
    servletRegistrationBean.setServlet(new StatViewServlet());
    servletRegistrationBean.addUrlMappings("/druid/*");
    return servletRegistrationBean;
  }

  @Bean
  public StatFilter statFilter() {
    StatFilter statFilter = new StatFilter();
    statFilter.setLogSlowSql(true);
    statFilter.setMergeSql(true);
    statFilter.setSlowSqlMillis(1000);

    return statFilter;
  }

  @Bean
  public WallFilter wallFilter() {
    WallFilter wallFilter = new WallFilter();

    // 允许执行多条SQL
    WallConfig config = new WallConfig();
    config.setMultiStatementAllow(true);
    wallFilter.setConfig(config);

    return wallFilter;
  }
}
